package com.yanqu.road.server.logic.battle;

import com.yanqu.road.entity.config.battle.BattleResult;
import com.yanqu.road.entity.config.battle.BattleUnionResult;
import com.yanqu.road.entity.config.battle.PatronsBattleDetail;
import com.yanqu.road.entity.config.patrons.PatronsInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.player.UserPatronsSkill;
import com.yanqu.road.entity.unioncampwar.config.UnionCampWarBuffConfig;
import com.yanqu.road.logic.pb.PatronsPb;
import com.yanqu.road.pb.patrons.PatronsProto;
import com.yanqu.road.server.logic.calc.CalculationManager;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.PatronsMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

public class BattleManager {

	private static Logger logger = LogManager.getLogger(BattleManager.class.getName());


	//把门客的技能加成提前算好传到跨服
	public static List<UserPatrons> crossOreWarPatrons(List<UserPatrons> patronsList){
		List<UserPatrons> clonePatronsList = new ArrayList<>();
		for (UserPatrons patrons : patronsList) {
			clonePatronsList.add(patrons.cloneUserPatrons());
		}
		skillEffect(clonePatronsList);
		return clonePatronsList;
	}

	//计算出加成后的赚速血量(本服的盐场活动)
	public static List<UserPatrons> getCalOreWarEarnSpeed(List<UserPatrons> patronsList){
		List<UserPatrons> clonePatronsList = new ArrayList<>();
		for (UserPatrons patrons : patronsList) {
			clonePatronsList.add(patrons.cloneUserPatrons());
		}
		skillEffect(clonePatronsList);
		for (UserPatrons userPatrons : clonePatronsList) {
			BigInteger ability = userPatrons.getAbility();
			userPatrons.setOreWarEarnSpeed(new BigDecimal(ability).multiply(BigDecimal.valueOf(((double)userPatrons.getBattleAddition()) / 1000)).
					setScale(0, BigDecimal.ROUND_UP).toBigInteger());
		}
		return clonePatronsList;
	}

	/**
	 * 战斗 全部走这边
	 */
	public static BattleResult battle(long userId, List<UserPatrons> patronsList, long enemyUserId, List<UserPatrons> enemyPatronsList,
		int buffAddition, boolean isSkillEffect, boolean skillIsBothEffect) {
//		logger.info("battle log start================================================");
		BattleResult battleResult = new BattleResult();
		battleResult.setEnemyUserId(enemyUserId);
		List<UserPatrons> clonePatronsList = new ArrayList<>();
		List<Integer> patronsIdList = new ArrayList<>();
		for (UserPatrons patrons : patronsList) {
			patronsIdList.add(patrons.getPatronsId());
			clonePatronsList.add(patrons.cloneUserPatrons());
		}

		List<UserPatrons> cloneEnemyPatronsList = new ArrayList<>();
		for (UserPatrons patrons : enemyPatronsList) {
			cloneEnemyPatronsList.add(patrons.cloneUserPatrons());
		}

		if(isSkillEffect) {
			//门客技能作用
			skillEffect(clonePatronsList);
			//对手技能效果也生效
			if (skillIsBothEffect) {
				skillEffect(cloneEnemyPatronsList);
			}
		}

//		logger.info("log userId:{} patrons info-------------", userId);
		for (UserPatrons userPatrons : clonePatronsList) {
			userPatrons.setCurrentBlood(userPatrons.getAbility());
			BigInteger oldBlood = userPatrons.getCurrentBlood();
			BigDecimal blood = new BigDecimal(oldBlood);
			blood = blood.multiply(BigDecimal.valueOf(userPatrons.getBattleAddition())).divide(BigDecimal.valueOf(1000),
					CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
			blood = blood.multiply(BigDecimal.valueOf(1000 + buffAddition)).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP);
			userPatrons.setCurrentBlood(blood.toBigInteger());
			userPatrons.setTotalBlood(userPatrons.getCurrentBlood());
//			logger.info("patronsId:{},ability:{}", userPatrons.getPatronsId(), userPatrons.getTotalBlood());
		}

//		logger.info("log enemyUserId:{} patrons info-------------", enemyUserId);
		for (UserPatrons userPatrons : cloneEnemyPatronsList) {
			userPatrons.setCurrentBlood(userPatrons.getAbility());
			BigInteger oldBlood = userPatrons.getCurrentBlood();
			userPatrons.setCurrentBlood(new BigDecimal(oldBlood).multiply(BigDecimal.valueOf(userPatrons.getBattleAddition())).
					divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).toBigInteger());
			userPatrons.setTotalBlood(userPatrons.getCurrentBlood());
//			logger.info("patronsId:{},ability:{}", userPatrons.getPatronsId(), userPatrons.getTotalBlood());
		}
		int enemyPatronsCount = cloneEnemyPatronsList.size();
//		logger.info("log battle start -------------");
		while (true) {
			PatronsBattleDetail patronsBattleDetail;
			// 攻方先出手
			if (clonePatronsList.size() > 0 && cloneEnemyPatronsList.size() > 0) {
				UserPatrons myPatrons = clonePatronsList.get(0);
				UserPatrons enemyPatrons = cloneEnemyPatronsList.get(0);
//				logger.info("battle pre userId:{},patronsId:{},totalBlood:{},curBlood:{}", userId, myPatrons.getPatronsId(),
//						myPatrons.getTotalBlood(), myPatrons.getCurrentBlood());
//				logger.info("battle pre enemyUserId:{},patronsId:{},totalBlood:{},curBlood:{}", enemyUserId,
//						enemyPatrons.getPatronsId(), enemyPatrons.getTotalBlood(), enemyPatrons.getCurrentBlood());
				patronsBattleDetail = patronsBattle(myPatrons, enemyPatrons);
//				logger.info("battle after userId:{},patronsId:{},totalBlood:{},curBlood:{}", userId, myPatrons.getPatronsId(),
//						myPatrons.getTotalBlood(), myPatrons.getCurrentBlood());
//				logger.info("battle after enemyUserId:{},patronsId:{},totalBlood:{},curBlood:{}", enemyUserId,
//						enemyPatrons.getPatronsId(), enemyPatrons.getTotalBlood(), enemyPatrons.getCurrentBlood());
			} else {
				logger.info("战斗数据出错 patrons size=={},enemy patrons size=={},userId=={},enemyUserId=={}",
						clonePatronsList.size(), cloneEnemyPatronsList.size(), userId, enemyUserId);
				break;
			}

			if (clonePatronsList.get(0).getCurrentBlood().compareTo(BigInteger.ZERO) <= 0) {
				clonePatronsList.remove(0);
			}
			if (cloneEnemyPatronsList.get(0).getCurrentBlood().compareTo(BigInteger.ZERO) <= 0) {
				cloneEnemyPatronsList.remove(0);
			}
			if(null != patronsBattleDetail) {
				battleResult.getPatronsBattleDetailList().add(patronsBattleDetail);
			}

			//全部打完则退出战斗
			if (clonePatronsList.size() == 0) {//对方获胜
				battleResult.setWinUserId(enemyUserId);
				break;
			}

			if (cloneEnemyPatronsList.size() == 0) {
				battleResult.setWinUserId(userId);
				break;
			}
		}

		battleResult.setKillPatronsCount(enemyPatronsCount - cloneEnemyPatronsList.size());
		battleResult.setEnemyPatronsList(enemyPatronsList);
		battleResult.setMyPatronsIdList(patronsIdList);
//		logger.info("battle log end================================================");
		return battleResult;
	}

	//获取盐场战斗技能加成，算好了发到跨服
	public static List<UserPatrons> getCloneSkillOreWarAddPatrons(List<UserPatrons> patronsList){
		List<UserPatrons> clonePatronsList = new ArrayList<>();
		for (UserPatrons patrons : patronsList) {
			UserPatrons cloneUserPatrons = patrons.cloneUserPatrons();
			cloneUserPatrons.setOreWarBattleAddition(cloneUserPatrons.getBattleAddition());
			clonePatronsList.add(cloneUserPatrons);
		}
		for (UserPatrons cUserPatrons : clonePatronsList) {
			if(null != cUserPatrons.getSkillList()){
				for(UserPatronsSkill patronsSkill : cUserPatrons.getSkillList()){
					skillOreWarPatrons(patronsSkill, clonePatronsList);
				}
			}
		}
		return clonePatronsList;
	}

	//新增个字段把门客的技能加成算上去
	private static void skillOreWarPatrons(UserPatronsSkill userPatronsSkill, List<UserPatrons> patronsList) {
		SkillInfo skillInfo = SkillMgr.getSkillInfo(userPatronsSkill.getSkillId());
		if(skillInfo == null){
			return;
		}
		if (skillInfo.getType() != eSkillType.BattleEffect.getValue()) {//不是出战技能
			return;
		}
		//技能生效计算
		int addition = SkillMgr.getSkillAddition(skillInfo, userPatronsSkill.getSkillLv());
		int param3 = skillInfo.getParamList().get(2);
		for(UserPatrons userPatrons : patronsList){
			PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(userPatrons.getPatronsId());
			if(patronsInfo.getOccupation() == param3) {
				userPatrons.setOreWarBattleAddition(userPatrons.getOreWarBattleAddition() + addition);
			}
		}
	}

	/**
	 * 人才技能生效
	 */
	public static void skillEffect(List<UserPatrons> patronsList) {
		for (UserPatrons userPatrons : patronsList) {
			if(null != userPatrons.getSkillList()){
				for(UserPatronsSkill patronsSkill : userPatrons.getSkillList()){
					skillEffectPatrons(patronsSkill, patronsList);
				}
			}
		}
	}

	/**
	 * 技能对门客产生效果
	 */
	private static void skillEffectPatrons(UserPatronsSkill userPatronsSkill, List<UserPatrons> patronsList) {
		SkillInfo skillInfo = SkillMgr.getSkillInfo(userPatronsSkill.getSkillId());
		if (skillInfo.getType() != eSkillType.BattleEffect.getValue()) {//不是出战技能
			return;
		}
		//技能生效计算
		int addition = SkillMgr.getSkillAddition(skillInfo, userPatronsSkill.getSkillLv());
		int param3 = skillInfo.getParamList().get(2);
		for(UserPatrons userPatrons : patronsList){
			PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(userPatrons.getPatronsId());
			if(patronsInfo.getOccupation() == param3) {
				userPatrons.setBattleAddition(userPatrons.getBattleAddition() + addition);
			}
		}
	}

	private static PatronsBattleDetail patronsBattle(UserPatrons myPatrons, UserPatrons enemyPatrons) {

		PatronsBattleDetail battleDetail = new PatronsBattleDetail();

		BigInteger myDamage = myPatrons.getCurrentBlood();
		BigInteger enemyDamage = enemyPatrons.getCurrentBlood();
		enemyPatrons.setCurrentBlood(enemyPatrons.getCurrentBlood().subtract(myDamage));
		myPatrons.setCurrentBlood(myPatrons.getCurrentBlood().subtract(enemyDamage));

		battleDetail.setMyPatronsId(myPatrons.getPatronsId());
		battleDetail.setMyPatronsCurrentBlood(myPatrons.getCurrentBlood());
		battleDetail.setMyPatronsTotalBlood(myPatrons.getTotalBlood());

		battleDetail.setEnemyPatronsId(enemyPatrons.getPatronsId());
		battleDetail.setEnemyPatronsCurrentBlood(enemyPatrons.getCurrentBlood());
		battleDetail.setEnemyPatronsTotalBlood(enemyPatrons.getTotalBlood());

		return battleDetail;
	}

	private static PatronsBattleDetail patronsBattle(UserPatrons myPatrons, UserPatrons enemyPatrons, int hpRevertAddition, BigInteger hpRevertValue) {

		PatronsBattleDetail battleDetail = new PatronsBattleDetail();

		BigInteger myDamage = myPatrons.getCurrentBlood();
		BigInteger enemyDamage = enemyPatrons.getCurrentBlood();
		enemyPatrons.setCurrentBlood(enemyPatrons.getCurrentBlood().subtract(myDamage));
		myPatrons.setCurrentBlood(myPatrons.getCurrentBlood().subtract(enemyDamage));

		battleDetail.setMyPatronsId(myPatrons.getPatronsId());
		battleDetail.setMyPatronsCurrentBlood(myPatrons.getCurrentBlood());
		battleDetail.setMyPatronsTotalBlood(myPatrons.getTotalBlood());

		battleDetail.setEnemyPatronsId(enemyPatrons.getPatronsId());
		battleDetail.setEnemyPatronsCurrentBlood(enemyPatrons.getCurrentBlood());
		battleDetail.setEnemyPatronsTotalBlood(enemyPatrons.getTotalBlood());
		battleDetail.setEnemyUserId(enemyPatrons.getUserId());

		//战斗结束恢复最大血量的千分比
		BigInteger oldBlood = myPatrons.getCurrentBlood();
		if (oldBlood.compareTo(BigInteger.ZERO) > 0) {
			BigInteger revertBlood = new BigDecimal(myPatrons.getTotalBlood()).multiply(BigDecimal.valueOf(hpRevertAddition).divide(BigDecimal.valueOf(1000), 2, BigDecimal.ROUND_HALF_UP)).
					setScale(0, BigDecimal.ROUND_UP).toBigInteger().add(hpRevertValue);
			myPatrons.setCurrentBlood(oldBlood.add(revertBlood));
			battleDetail.setMyPatronsRevertBlood(revertBlood);
		}

		return battleDetail;
	}

	public static BigInteger getPatronsListAbility(List<UserPatrons> patronsList) {
		List<UserPatrons> clonePatronsList = new ArrayList<>();
		for (UserPatrons patrons : patronsList) {
			clonePatronsList.add(patrons.cloneUserPatrons());
		}

		skillEffect(clonePatronsList);
		BigInteger totalAbility = BigInteger.ZERO;
		for (UserPatrons userPatrons : clonePatronsList) {
			BigDecimal blood = new BigDecimal(userPatrons.getAbility());
			blood = blood.multiply(BigDecimal.valueOf(userPatrons.getBattleAddition())).divide(BigDecimal.valueOf(1000),
					0, BigDecimal.ROUND_UP);
			totalAbility = totalAbility.add(blood.toBigInteger());
		}
		return totalAbility;
	}

	public static List<PatronsProto.PatronsSimpleTempMsg> getUnionCampWarAttackPatronsMsg(List<UserPatrons> patronsList, int addition) {
		List<PatronsProto.PatronsSimpleTempMsg> msgList = new ArrayList<>();
		List<UserPatrons> clonePatronsList = new ArrayList<>();
		for (UserPatrons patrons : patronsList) {
			clonePatronsList.add(patrons.cloneUserPatrons());
		}

		//门客技能作用
		skillEffect(clonePatronsList);
		for (UserPatrons userPatrons : clonePatronsList) {
			userPatrons.setCurrentBlood(userPatrons.getAbility());
			BigInteger oldBlood = userPatrons.getCurrentBlood();
			BigDecimal blood = new BigDecimal(oldBlood);
			blood = blood.multiply(BigDecimal.valueOf(userPatrons.getBattleAddition() + addition)).divide(BigDecimal.valueOf(1000),
					CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
			userPatrons.setCurrentBlood(blood.toBigInteger());
			userPatrons.setTotalBlood(userPatrons.getCurrentBlood());

			PatronsProto.PatronsSimpleTempMsg.Builder patronsMsg = PatronsPb.parsePatronsSimpleTempMsg(userPatrons);
			patronsMsg.setBlood(userPatrons.getTotalBlood().toString());
			msgList.add(patronsMsg.build());
		}

		return msgList;
	}

	/**
	 * 商帮战斗专用,打商会所有门客,buff效果战斗结束恢复门客最大血量的千分比
	 */
	public static BattleUnionResult battleByUnionCampWar(long userId, List<UserPatrons> patronsList, String enemyUnionId, List<UserPatrons> enemyPatronsList,
														 UnionCampWarBuffConfig buffConfig, List<String> avgAbilityList) {
		List<BigDecimal> gradeAbilityList = new ArrayList<>();
		for (String ability : avgAbilityList) {
			gradeAbilityList.add(new BigDecimal(ability));
		}

		BattleUnionResult battleResult = new BattleUnionResult();
		battleResult.setEnemyUnionId(enemyUnionId);
		List<UserPatrons> clonePatronsList = new ArrayList<>();
		List<Integer> patronsIdList = new ArrayList<>();
		for (UserPatrons patrons : patronsList) {
			patronsIdList.add(patrons.getPatronsId());
			clonePatronsList.add(patrons.cloneUserPatrons());
		}

		List<UserPatrons> cloneEnemyPatronsList = new ArrayList<>();
		for (UserPatrons patrons : enemyPatronsList) {
			cloneEnemyPatronsList.add(patrons.cloneUserPatrons());
		}
		int enemyPatronsCount = cloneEnemyPatronsList.size();
		//击败的门客列表
		List<UserPatrons> defatedEnemyPatrons = new ArrayList<>();
		//击败我方的最后一个对方门客
		UserPatrons lastEnemyWinPatrons = null;


		int hpRevertAmount = 0;

		while (true) {
			PatronsBattleDetail patronsBattleDetail;

			int hpRevertAddition = 0;//恢复血量千分比
			BigInteger hpRevertValue = BigInteger.ZERO;//回复固定值
			if (buffConfig != null) {
				int killIndex = defatedEnemyPatrons.size() + 1;
				if (hpRevertAmount < buffConfig.getEffectMax()) {
					if (buffConfig.getPerNum() == 0 || killIndex % buffConfig.getPerNum() == 0) {
						hpRevertAmount++;
						if (buffConfig.getBuffGrade() == 0 || gradeAbilityList.isEmpty() || buffConfig.getBuffGrade() > gradeAbilityList.size()) {//玩家档位为0，buff为百分比，恢复效果直接用配置值
							hpRevertAddition = buffConfig.getRevertHpPer();
						} else {//恢复固定值=玩家档位赚钱平均值*配置系数
							hpRevertValue = gradeAbilityList.get(buffConfig.getBuffGrade() - 1).multiply(BigDecimal.valueOf(buffConfig.getRevertHpPer())).divide(BigDecimal.valueOf(1000), 0, BigDecimal.ROUND_UP).toBigInteger();
						}
					}
				}
			}
			// 攻方先出手
			if (clonePatronsList.size() > 0 && cloneEnemyPatronsList.size() > 0) {
				patronsBattleDetail = patronsBattle(clonePatronsList.get(0), cloneEnemyPatronsList.get(0), hpRevertAddition, hpRevertValue);
				lastEnemyWinPatrons = cloneEnemyPatronsList.get(0);
			} else {
				logger.error("战斗数据出错 patrons size=={},enemy patrons size=={},userId=={},enemyUnionId=={}",
						clonePatronsList.size(), cloneEnemyPatronsList.size(), userId, enemyUnionId);
				break;
			}

			if (clonePatronsList.get(0).getCurrentBlood().compareTo(BigInteger.ZERO) <= 0) {
				clonePatronsList.remove(0);
			}
			if (cloneEnemyPatronsList.get(0).getCurrentBlood().compareTo(BigInteger.ZERO) <= 0) {
				defatedEnemyPatrons.add(cloneEnemyPatronsList.get(0));
				cloneEnemyPatronsList.remove(0);
			}
			if (null != patronsBattleDetail) {
				battleResult.getPatronsBattleDetailList().add(patronsBattleDetail);
			}

			//全部打完则退出战斗
			if (clonePatronsList.size() == 0) {//对方获胜
				break;
			}

			if (cloneEnemyPatronsList.size() == 0) {
				break;
			}
		}

		battleResult.setKillPatronsCount(enemyPatronsCount - cloneEnemyPatronsList.size());
		battleResult.setDefeatedEnemyPatronsList(defatedEnemyPatrons);
		battleResult.setMyPatronsIdList(patronsIdList);
		battleResult.setLastFightEnemyPatrons(lastEnemyWinPatrons);

		return battleResult;
	}
}
